package com.mxpio.erp.plm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.enums.PlmEnums;
import com.mxpio.erp.common.plm.entity.*;
import com.mxpio.erp.common.plm.service.*;
import com.mxpio.erp.common.plm.vo.ProjectInfoDetailVO;
import com.mxpioframework.camunda.service.BpmnFlowService;
import com.mxpioframework.common.exception.MBootException;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.security.service.impl.BaseServiceImpl;
import com.mxpioframework.security.util.SecurityUtils;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 项目暂停恢复操作记录表
 */
@Service
public class ProjectPauseOperationServiceImpl extends BaseServiceImpl<ProjectPauseOperation> implements ProjectPauseOperationService {

    @Autowired
    private ProjectInfoService projectInfoService;

    @Autowired
    private ProjectPauseOperationService projectPauseOperationService;

    @Autowired
    private ProjectInfoStatusHistoryService projectInfoStatusHistoryService;

    @Autowired
    private ProjectRecoveryOperationService projectRecoveryOperationService;

    @Autowired
    private ProjectInfoCompleteService projectInfoCompleteService;

    @Autowired
    private ProjectInfoEndService projectInfoEndService;

    @Autowired
    private ProjectInfoChangeService projectInfoChangeService;

    @Autowired
    private ProjectTaskService projectTaskService;

    @Autowired
    private BpmnFlowService bpmnFlowService;
    @Autowired
    private ProjectInfoRecordDraftService projectInfoRecordDraftService;
    @Autowired
    private ProjectDeliverableService projectDeliverableService;
    @Autowired
    private ProjectInfoRecordDeliverableDraftService projectInfoRecordDeliverableDraftService;


    /**
     * 暂停项目
     * @param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> stopProById(ProjectPauseOperation pauseOperation) {
        String bizNo = pauseOperation.getBizNo();
        ProjectPauseOperation operation = this.getById(ProjectPauseOperation.class,bizNo);
        if (operation == null){//判断.实体类是否找到或者审核单是否通过
            return Result.error("项目暂停恢复操作表不存在,无法暂停");
        }
        //检测当前项目是否存在未审核的暂停申请，若有，先完成审核
//        Criteria criteria = Criteria.create().addCriterion("proCode", Operator.EQ, operation.getProCode());
//        List<ProjectPauseOperation> list = this.list(ProjectPauseOperation.class, criteria);
//        for (ProjectPauseOperation item : list){
//            if (item.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())||
//                item.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())){
//                return Result.error("项目暂停恢复操作表中存在未审核的暂停申请，请先完成审核");
//            }
//        }

        ProjectInfo projectInfo = projectInfoService.getById(ProjectInfo.class, operation.getProCode());//通过申请单找到对应的项目信息
        if (!projectInfo.getProStatus().equals(PlmEnums.ProStatus.EXECUT.getCode())){
            return Result.error("项目状态不是执行中，无法暂停");
        }
        //判断暂停操作是否通过
        if (pauseOperation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())){
            operation.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());
            operation.setBpmnStatus(pauseOperation.getBpmnStatus());
            this.update(pauseOperation);
        //取出当前的项目状态
        String proStatus = projectInfo.getProStatus();
        //更新项目状态为暂停状态
        projectInfo.setProStatus(PlmEnums.ProStatus.PAUSE.getCode());
        projectInfoService.update(projectInfo);
        //记录状态历史
        ProjectInfoStatusHistory projectInfoStatusHistory = new ProjectInfoStatusHistory();//创建状态历史
        projectInfoStatusHistory.setProCode(projectInfo.getProCode());
        projectInfoStatusHistory.setProStatusBefore(proStatus);
        projectInfoStatusHistory.setProStatusAfter(projectInfo.getProStatus());
        projectInfoStatusHistory.setChangeTime(new Date());
        // 设置变更人，这就为暂停单申请人
        projectInfoStatusHistory.setChangeUser(operation.getApplyUser());
        // 设置备注信息，可以根据具体业务逻辑添加
        projectInfoStatusHistory.setRemark("项目暂停");
        projectInfoStatusHistoryService.save(projectInfoStatusHistory);

        //对项目对应的任务中的项目状态和项目名称进行更改
        Criteria c = Criteria.create().addCriterion("proCode", Operator.EQ, projectInfo.getProCode());
        List<ProjectTask> tasks = projectTaskService.list(ProjectTask.class, c);
        for (ProjectTask projectTask : tasks){
            projectTask.setProStatus(projectInfo.getProStatus());
            projectTaskService.update(projectTask);
        }
        return Result.OK(projectInfo);
        }else if (pauseOperation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode())){
            operation.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());
            operation.setBpmnStatus("不同意");
            this.update(operation);
            return Result.OK("审批未通过，请重新提交");
        }
        return Result.error("状态不对");

    }

    /**
     * 添加暂停申请
     * @param properties
     */
    @Override
    @Transactional
    public Result<?> saveAll(String key, String loginUsername, String businessKey, Map<String, Object> properties) {
//        String proCode = pauseOperation.getProCode();
        String proCode = (String) properties.get("proCode");
        Criteria criteria = Criteria.create().addCriterion("proCode", Operator.EQ, proCode);
        //判断项目是否是执行中的状态
        ProjectInfo projectInfo = projectInfoService.getById(ProjectInfo.class, proCode);
        if (projectInfo == null || !projectInfo.getProStatus().equals(PlmEnums.ProStatus.EXECUT.getCode())){
            return Result.error("项目不是执行中的状态，不能暂停");
        }
        //判断此时是否有其他的工作流在审核
        List<ProjectInfoChange> list1 = projectInfoChangeService.list(ProjectInfoChange.class, criteria);
        for (ProjectInfoChange projectInfoChange : list1){
            if (projectInfoChange.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())||
                    projectInfoChange.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())){
                return Result.error("项目有变更工作流正在审核,不能暂停");
            }
        }
        List<ProjectInfoEnd> list2 = projectInfoEndService.list(ProjectInfoEnd.class, criteria);
        for (ProjectInfoEnd projectInfoEnd : list2){
            if (projectInfoEnd.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())||
                    projectInfoEnd.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())){
                return Result.error("项目有终止工作流在审核中,不能暂停");
            }
        }
//        List<ProjectRecoveryOperation> list3 = projectRecoveryOperationService.list(ProjectRecoveryOperation.class, criteria);
//        for (ProjectRecoveryOperation projectRecoveryOperation : list3){
//            if (projectRecoveryOperation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())||
//                    projectRecoveryOperation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())){
//                return Result.error("项目有恢复工作流在审核中,不能暂停");
//            }
//        }
        List<ProjectInfoComplete> list4 = projectInfoCompleteService.list(ProjectInfoComplete.class, criteria);
        for (ProjectInfoComplete projectInfoComplete : list4){
            if (projectInfoComplete.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())||
                    projectInfoComplete.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())){
                return Result.error("项目有结项工作流在审核中,不能暂停");
            }
        }

        List<ProjectPauseOperation> list = this.list(ProjectPauseOperation.class, criteria);
        for (ProjectPauseOperation operation : list){
            if (operation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())||
               operation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())){
                return Result.error("暂停申请正在审核中，请勿重复提交");
            }
        }
//        //判断恢复单，是否有还在申请恢复的未完成审核的单子
//        List<ProjectRecoveryOperation> list1 = projectRecoveryOperationService.list(ProjectRecoveryOperation.class, criteria);
//        for (ProjectRecoveryOperation operation : list1){
//            if (operation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())||
//               operation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())){
//                return Result.error("当前的项目已暂停，并且未恢复");
//            }
//        }
        //
        ProjectPauseOperation pauseOperation = new ProjectPauseOperation();
        pauseOperation.setBpmnStatus(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode());
        pauseOperation.setProCode((String) properties.get("proCode"));
//        pauseOperation.setPlanRestoreTime((Date) properties.get("planRestoreTime"));
        pauseOperation.setReason((String) properties.get("reason"));
        pauseOperation.setAttachment(properties.get("attachment") !=null ? properties.get("attachment").toString():null);
        pauseOperation.setApplyUser(SecurityUtils.getLoginUsername());
        pauseOperation.setApplyTime(new Date());
        pauseOperation.setIsAuditEnd(CommonEnums.YesNo.NO.getCode());

        //string类型转化为Date类型
        String dateStr =(String) properties.get("planRestoreTime");
        if (dateStr != null) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate date = LocalDate.parse(dateStr, formatter);
            Date oldDate = Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
            pauseOperation.setPlanRestoreTime(oldDate);
        }

        this.save(pauseOperation);
        String bizNo = pauseOperation.getBizNo();
        properties.put("bizNo", bizNo);

        //将信息 存入草稿表
        ProjectInfoRecordDraft projectInfoRecordDraft = new ProjectInfoRecordDraft();
        BeanUtil.copyProperties(projectInfo, projectInfoRecordDraft);
        projectInfoRecordDraft.setBizNo(bizNo);
        projectInfoRecordDraftService.save(projectInfoRecordDraft);
        List<ProjectDeliverable> list6 = projectDeliverableService.list(ProjectDeliverable.class, Criteria.create().addCriterion("proCode", Operator.EQ, proCode));
        for (ProjectDeliverable projectDeliverable : list6){
            ProjectInfoRecordDeliverableDraft projectInfoRecordDeliverableDraft = new ProjectInfoRecordDeliverableDraft();
            BeanUtil.copyProperties(projectDeliverable, projectInfoRecordDeliverableDraft,"id");
            projectInfoRecordDeliverableDraft.setBizNo(bizNo);
            projectInfoRecordDeliverableDraftService.save(projectInfoRecordDeliverableDraft);
        }

        //发起工作流
        ProcessInstance processInstance = bpmnFlowService.startWithFormByKey(key, loginUsername, businessKey, properties);
        ProjectPauseOperation byId = projectPauseOperationService.getById(ProjectPauseOperation.class, bizNo);
        byId.setProcessInstanceId(processInstance.getId());
        projectPauseOperationService.update(byId);
        return Result.OK(byId);
    }

    @Override
    @Transactional
    public ProjectPauseOperation getOne(String bizNo) {
        ProjectPauseOperation byId = this.getById(ProjectPauseOperation.class, bizNo);
//        List<ProjectPauseOperation> list = this.list(ProjectPauseOperation.class, Criteria.create().addCriterion("bizNo", Operator.EQ, bizNo));
//        for (ProjectPauseOperation operation : list){
//            if (operation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())||operation.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())||
//                    operation.getIsAuditEnd().equals(CommonEnums.YesNo.NO.getCode())){
//                return operation;
//            }
//        }
        return byId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> getDetail(String bizNo) {
        ProjectInfoDetailVO projectInfoDetailVO = new ProjectInfoDetailVO();
        ProjectInfoRecordDraft infoRecordDraft = JpaUtil.linq(ProjectInfoRecordDraft.class).equal("bizNo", bizNo).findOne();
        List<ProjectInfoRecordDeliverableDraft> deliverableDrafts = projectInfoRecordDeliverableDraftService.list(ProjectInfoRecordDeliverableDraft.class, Criteria.create().addCriterion("bizNo", Operator.EQ, bizNo));
        ProjectPauseOperation byId = this.getById(ProjectPauseOperation.class, bizNo);
        projectInfoDetailVO.setProjectPauseyOperation(byId);
        projectInfoDetailVO.setProjectInfoRecordDraft(infoRecordDraft);
        projectInfoDetailVO.setProjectInfoRecordDeliverableDrafts(deliverableDrafts);
        return Result.OK(projectInfoDetailVO);
    }

}
